﻿//------------------------------------------------------------------------------
//  Namespace: FruitVentDesign.Controls
//  
//  Function： N/A
//  Name： ColorPicker
//  
//  Ver       Time                     Author
//  0.10      2021/11/8 18:19:15                   Benedict Deng
//
//  Description:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

using FruitVentDesign.Media;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace FruitVentDesign.Controls
{
    public class ColorPicker : ContentControl
    {
        public ColorPicker()
        {
            Loaded += ColorPicker_Loaded;
        }

        #region 私有方法
        private void ColorPicker_Loaded(object sender, RoutedEventArgs e)
        {
            colorView.PreviewMouseLeftButtonUp += ColorView_PreviewMouseLeftButtonUp;
            White.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Gray.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Yellow.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Orange.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            HotPink.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Peru.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            RoyalBlue.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            SkyBlue.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Teal.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Tomato.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Black.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Sienna.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Gold.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            DarkBlue.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Magenta.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            LimeGreen.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Lime.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Blue.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Green.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            Red.PreviewMouseLeftButtonUp += RectColor_PreviewMouseLeftButtonUp;
            ThumbH.ValueChanged += ThumbH_ValueChanged;
            ThumbSB.ValueChanged += ThumbSB_ValueChanged;
            TextR.LostFocus += TextBox_LostFocus;
            TextG.LostFocus += TextBox_LostFocus;
            TextB.LostFocus += TextBox_LostFocus;
            TextA.LostFocus += TextBox_LostFocus;
            TextHex.LostFocus += HexText_LostFocus;
        }

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            //错误的数据，则使用上次的正确数据
            if (!int.TryParse(TextR.Text, out int Rvalue) || (Rvalue > 255 || Rvalue < 0))
            {
                TextR.Text = R.ToString();
                return;
            }

            if (!int.TryParse(TextG.Text, out int Gvalue) || (Gvalue > 255 || Gvalue < 0))
            {
                TextG.Text = G.ToString();
                return;
            }

            if (!int.TryParse(TextB.Text, out int Bvalue) || (Bvalue > 255 || Bvalue < 0))
            {
                TextB.Text = _B.ToString();
                return;
            }

            if (!int.TryParse(TextA.Text, out int Avalue) || (Avalue > 255 || Avalue < 0))
            {
                TextA.Text = A.ToString();
                return;
            }
            R = Rvalue; G = Gvalue; _B = Bvalue; A = Avalue;

            RgbaColor Hcolor = new RgbaColor(R, G, _B, A);
            SelectedBrush = Hcolor.SolidColorBrush;

            TextHex.Text = Hcolor.HexString;

            H = Hcolor.HsbaColor.H;
            HsbaColor Hcolor2 = new HsbaColor(H, 1, 1, 1);
            ViewSelectColor_First.Fill = Hcolor2.SolidColorBrush;

            double xpercent = S = Hcolor.HsbaColor.S;
            double ypercent = B = 1 - Hcolor.HsbaColor.B;

            double Ypercent = Hcolor.HsbaColor.H / 360;

            ThumbH.SetTopLeftByPercent(1, Ypercent);
            ThumbSB.SetTopLeftByPercent(xpercent, ypercent);
        }

        private void HexText_LostFocus(object sender, RoutedEventArgs e)
        {
            RgbaColor Hcolor = new RgbaColor(TextHex.Text);

            SelectedBrush = Hcolor.SolidColorBrush;
            TextR.Text = Hcolor.R.ToString();
            TextG.Text = Hcolor.G.ToString();
            TextB.Text = Hcolor.B.ToString();
            TextA.Text = Hcolor.A.ToString();

            H = Hcolor.HsbaColor.H;
            HsbaColor Hcolor2 = new HsbaColor(H, 1, 1, 1);
            ViewSelectColor_First.Fill = Hcolor2.SolidColorBrush;

            double xpercent = S = Hcolor.HsbaColor.S;
            double ypercent = B = 1 - Hcolor.HsbaColor.B;

            double Ypercent = Hcolor.HsbaColor.H / 360;

            ThumbH.SetTopLeftByPercent(1, Ypercent);
            ThumbSB.SetTopLeftByPercent(xpercent, ypercent);
        }

        private void ThumbH_ValueChanged(double xpercent, double ypercent)
        {
            H = 360 * ypercent;
            HsbaColor Hcolor = new HsbaColor(H, 1, 1, 1);
            ViewSelectColor_First.Fill = Hcolor.SolidColorBrush;

            Hcolor = new HsbaColor(H, S, B, 1);
            SelectedBrush = Hcolor.SolidColorBrush;

            ColorChange(Hcolor.RgbaColor);
        }

        private void ThumbSB_ValueChanged(double xpercent, double ypercent)
        {
            S = xpercent;
            B = 1 - ypercent;
            HsbaColor Hcolor = new HsbaColor(H, S, B, 1);

            SelectedBrush = Hcolor.SolidColorBrush;

            ColorChange(Hcolor.RgbaColor);
        }

        private void ColorChange(RgbaColor Hcolor)
        {
            TextR.Text = Hcolor.R.ToString();
            TextG.Text = Hcolor.G.ToString();
            TextB.Text = Hcolor.B.ToString();
            TextA.Text = Hcolor.A.ToString();

            TextHex.Text = Hcolor.HexString;
        }

        private void RectColor_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            Brush brush = (sender as Rectangle).Fill;
            Color c = (Color)ColorConverter.ConvertFromString(brush.ToString());

            R = c.R; G = c.G; _B = c.B; A = c.A;

            RgbaColor Hcolor = new RgbaColor(R, G, _B, A);

            SelectedBrush = new SolidColorBrush(c);
            ColorChange(Hcolor);

            H = Hcolor.HsbaColor.H;
            HsbaColor Hcolor2 = new HsbaColor(H, 1, 1, 1);
            ViewSelectColor_First.Fill = Hcolor2.SolidColorBrush;

            double xpercent = S = Hcolor.HsbaColor.S;
            double ypercent = B = 1 - Hcolor.HsbaColor.B;

            double Ypercent = Hcolor.HsbaColor.H / 360;

            ThumbH.SetTopLeftByPercent(1, Ypercent);
            ThumbSB.SetTopLeftByPercent(xpercent, ypercent);
        }

        private void ColorView_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            IsDropDownOpen = !IsDropDownOpen;
            if (IsLoaded)
            {
                RgbaColor Hcolor = new RgbaColor(SelectedBrush);
                ColorChange(Hcolor);

                double xpercent = Hcolor.HsbaColor.S;
                double ypercent = 1 - Hcolor.HsbaColor.B;

                double Ypercent = Hcolor.HsbaColor.H / 360;

                ThumbH.SetTopLeftByPercent(1, Ypercent);
                ThumbSB.SetTopLeftByPercent(xpercent, ypercent);
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            colorView = Template.FindName("PART_ColorView", this) as Border;
            White = Template.FindName("White", this) as Rectangle;
            Gray = Template.FindName("Gray", this) as Rectangle;
            Yellow = Template.FindName("Yellow", this) as Rectangle;
            Orange = Template.FindName("Orange", this) as Rectangle;
            HotPink = Template.FindName("HotPink", this) as Rectangle;
            Peru = Template.FindName("Peru", this) as Rectangle;
            RoyalBlue = Template.FindName("RoyalBlue", this) as Rectangle;
            SkyBlue = Template.FindName("SkyBlue", this) as Rectangle;
            Teal = Template.FindName("Teal", this) as Rectangle;
            Tomato = Template.FindName("Tomato", this) as Rectangle;
            Black = Template.FindName("Black", this) as Rectangle;
            Sienna = Template.FindName("Sienna", this) as Rectangle;
            Gold = Template.FindName("Gold", this) as Rectangle;
            DarkBlue = Template.FindName("DarkBlue", this) as Rectangle;
            Magenta = Template.FindName("Magenta", this) as Rectangle;
            LimeGreen = Template.FindName("LimeGreen", this) as Rectangle;
            Lime = Template.FindName("Lime", this) as Rectangle;
            Blue = Template.FindName("Blue", this) as Rectangle;
            Green = Template.FindName("Green", this) as Rectangle;
            Red = Template.FindName("Red", this) as Rectangle;
            ThumbH = Template.FindName("ThumbH", this) as ThumbPro;
            ThumbSB = Template.FindName("ThumbSB", this) as ThumbPro;
            ViewSelectColor_First = Template.FindName("ViewSelectColor_First", this) as Rectangle;
            TextR = Template.FindName("TextR", this) as TextBox;
            TextG = Template.FindName("TextG", this) as TextBox;
            TextB = Template.FindName("TextB", this) as TextBox;
            TextA = Template.FindName("TextA", this) as TextBox;
            TextHex = Template.FindName("TextHex", this) as TextBox;
        }

        #endregion

        #region 依赖属性
        #region IsDropDownOpen property
        /// <summary>
        /// 下拉
        /// </summary>
        public static readonly DependencyProperty IconTemplateProperty =
            DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(ColorPicker), new PropertyMetadata(false));

        public bool IsDropDownOpen
        {
            get => (bool)GetValue(IconTemplateProperty);
            set => SetValue(IconTemplateProperty, value);
        }
        #endregion

        #region IsDropDownOpen property
        /// <summary>
        /// 选择的颜色
        /// </summary>
        public static readonly DependencyProperty SelectedBrushProperty =
            DependencyProperty.Register("SelectedBrush", typeof(SolidColorBrush), typeof(ColorPicker), 
                new FrameworkPropertyMetadata(Brushes.Black, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public SolidColorBrush SelectedBrush
        {
            get => (SolidColorBrush)GetValue(SelectedBrushProperty);
            set => SetValue(SelectedBrushProperty, value);
        }
        #endregion
        #endregion

        #region 字段

        private Border colorView;
        private Rectangle White;
        private Rectangle Gray;
        private Rectangle Yellow;
        private Rectangle Orange;
        private Rectangle HotPink;
        private Rectangle Peru;
        private Rectangle RoyalBlue;
        private Rectangle SkyBlue;
        private Rectangle Teal;
        private Rectangle Tomato;
        private Rectangle Black;
        private Rectangle Sienna;
        private Rectangle Gold;
        private Rectangle DarkBlue;
        private Rectangle Magenta;
        private Rectangle LimeGreen;
        private Rectangle Lime;
        private Rectangle Blue;
        private Rectangle Green;
        private Rectangle Red;

        private Rectangle ViewSelectColor_First;

        private ThumbPro ThumbH;
        private ThumbPro ThumbSB;

        private TextBox TextR;
        private TextBox TextG;
        private TextBox TextB;
        private TextBox TextA;
        private TextBox TextHex;

        private double H;
        private double S = 1;
        private double B = 1;

        private int R = 255;
        private int G = 255;
        private int _B = 255;
        private int A = 255;

        #endregion
    }
}